package testadventure;
import edu.clemson.cs.hamptos.adventure.AdventureCommand;
import edu.clemson.cs.hamptos.adventure.AdventureEngine;
import edu.clemson.cs.hamptos.adventure.AdventureLocation;
import edu.clemson.cs.hamptos.adventure.AdventureTarget;
import edu.clemson.cs.hamptos.adventure.AdventureWindow;
import edu.clemson.cs.hamptos.adventure.DoNotUnderstandException;
import edu.clemson.cs.hamptos.adventure.NoSuchTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

/**
 *<p>Implements the <code>AdventureLocation</code> interface. Uses script files
 * to create a frame work to guide the user through the progression of game with
 * its different locations.</p>
 * @author Nicks
 */
public class BaseLocation implements AdventureLocation {
    /**
     * <p>Constructs a new instance of <code>BaseLocation</code></p>
     */
    public BaseLocation() {
    }
    /**
     * <p>Constructs a new instance of Base location</p>
     * @param inBlob - of type <code>String</code>
     * @param itemMap - of type <code>HashMap</code>
     */
    public BaseLocation(String inBlob, HashMap<String, AdventureTarget>itemMap)
    {
        Scanner fieldScan = new Scanner(inBlob);
        fieldScan.useDelimiter(";\r\n");
        
        Scanner nameFieldScan = new Scanner(fieldScan.next());
        name = nameFieldScan.next();
        while(nameFieldScan.hasNext())
        {
            listeners.add(nameFieldScan.next());
        }
        
        description = fieldScan.next();
        Scanner itemScan = new Scanner(fieldScan.next());
        itemScan.useDelimiter("\r\n");
        while (itemScan.hasNext())
        {
            Scanner itemFieldScan = new Scanner(itemScan.next());
            
            String findIt = itemFieldScan.next();
            
            AdventureTarget toAdd = itemMap.get(findIt).clone();
            
            while(itemFieldScan.hasNext())
            {
                toAdd.addListener(itemFieldScan.next());
            }
            
            localTargs.add(toAdd);
            
            
        }
        
        Scanner exitScan = new Scanner(fieldScan.next());
        exitScan.useDelimiter("\r\n");
        while (exitScan.hasNext())
        {
            Scanner splitExitScan = new Scanner(exitScan.next());
            String nxtExit = splitExitScan.next();
            String exitName = splitExitScan.next();
            String exitTarg = splitExitScan.next();
            int exitEnable = splitExitScan.nextInt();
            
            ItemExit theClone = TheAdventure.exitMap.get(nxtExit).clone
                                             (exitName, exitTarg, exitEnable);
            localTargs.add(theClone);
        }
        
    }
    
    //class variables
    private String name;
    //descriptions of the object
    private String description= "";
    private HashSet<AdventureTarget> localTargs = 
                                     new HashSet<AdventureTarget>();
    
    //list of things triggered by entering this area
    protected HashSet<String> listeners = new HashSet<String>();
    ////
    /**
     * Returns the name of the location
     * @return - name of type <code>String</code>
     */
    public String getName()
    {
        return name;
    }
    
    @Override
    public String getDescription() {
        StringBuilder descr = new StringBuilder(description);
        Iterator<AdventureTarget> targsIt = localTargs.iterator();
        while (targsIt.hasNext())
        {
            String app = targsIt.next().getDescription();
            if (app.length() > 0)
            {
                descr.append("\n&nbsp;&nbsp;&nbsp;&nbsp;").append(app);
            }
        }
        return descr.toString();
    }

    @Override
    public void doCommand(AdventureCommand c, AdventureEngine e, 
                          AdventureWindow w) 
            throws DoNotUnderstandException  {
        throw new DoNotUnderstandException(c);
    }

    @Override
    public Set<AdventureTarget> getLocalTargets() {
        return localTargs;
    }

    @Override
    public void addLocalTarget(AdventureTarget t) {
        localTargs.add(t);
    }

    @Override
    public void removeLocalTarget(AdventureTarget t) {
        localTargs.remove(t);
    }
    
    @Override
    public boolean containsLocalTarget(AdventureTarget t) {
        return localTargs.contains(t);
    }
    
    @Override
    public AdventureTarget containsLocalTarget(String t) 
            throws NoSuchTargetException
    {
        Iterator<AdventureTarget> it = localTargs.iterator();
        while(it.hasNext())
        {
            AdventureTarget toCheck = it.next();
            if(toCheck.canBeReferredToAs(t))
            {
                return toCheck;
            }
        }
        throw new NoSuchTargetException(t);
    }

    @Override
    public void addListener(String target) {
        listeners.add(target);
    }

    @Override
    public void removeListener(String target) {
        listeners.remove(target);
    }

    @Override
    public void notifyListeners(AdventureEngine e, AdventureWindow w) {
        Iterator<String> it = listeners.iterator();
        while(it.hasNext())
        {
            try {
                String nxt = it.next();
                AdventureTarget t = containsLocalTarget(nxt);
                t.listen(e, w);
            } catch (NoSuchTargetException ex) {
                //suppress, shouldn't happen
                w.println("Oops, Listener wasn't there..." + ex.getItemName());
            }
        }
    }
}
